/*
 *Copyright (c) [2019] [name of copyright holder]
 *[Software Name] is licensed under the Mulan PSL v1.
 *You can use this software according to the terms and conditions of the Mulan PSL v1.
 *You may obtain a copy of Mulan PSL v1 at:
 *http://license.coscl.org.cn/MulanPSL
 *THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 *IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 *PURPOSE.
 *See the Mulan PSL v1 for more details.
 */

/*!
 * \autor captainpeng
 * \date 2018-12-29
 * \version 1.0
 * \copyright
 */

#ifndef MY_CHARLIB_HPP
#define MY_CHARLIB_HPP

#include<cctype>
#include<cwctype>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cwchar>

#include<string>

namespace my{
    
    template<typename CharT>
    class charLib;
	
    template<>
    class charLib<char>{
        charLib() = delete;
    public:
        using charType = char;
        using charPtr = char *;
        using intType = int;
        using strType = std::string;
	
        static intType empty(){
            return '\0';
        }

        static intType enter(){
            return '\n';
        }

        static intType eof(){
            return EOF;
        }
        
        static inline bool isalnum(charType ch){
            return static_cast<bool>(std::isalnum(ch));
        }

        static inline bool isalpha(charType ch){
            return static_cast<bool>(std::isalpha(ch));
        }

        static inline bool islower(charType ch){
            return static_cast<bool>(std::islower(ch));
        }

        static inline bool isupper(charType ch){
            return static_cast<bool>(std::isupper(ch));
        }

        static inline bool isdigit(charType ch){
            return static_cast<bool>(std::isdigit(ch));
        }

        static inline bool isxdigit(charType ch){
            return static_cast<bool>(std::isxdigit(ch));
        }

        static inline bool iscntrl(charType ch){
            return static_cast<bool>(std::iscntrl(ch));
        }

        static inline bool isgraph(charType ch){
            return static_cast<bool>(std::isgraph(ch));
        }

        static inline bool isspace(charType ch){
            return static_cast<bool>(std::isspace(ch));
        }

        static inline bool isblank(charType ch){
            return static_cast<bool>(std::isblank(ch));
        }

        static inline bool isprint(charType ch){
            return static_cast<bool>(std::isprint(ch));
        }

        static inline bool ispunct(charType ch){
            return static_cast<bool>(std::ispunct(ch));
        }

        static inline charType tolower(charType ch){
            return static_cast<charType>(std::tolower(ch));
        }

        static inline charType toupper(charType ch){
            return static_cast<charType>(std::toupper(ch));
        }

        static inline wint_t towchar(intType c){
            return std::btowc(c);
        }
        // 这是一个把 const char * 转换成 const wchar_t * 的函数
        static inline const wchar_t * towstr(const charType * src){
            static std::wstring buf;

            buf.clear();
            int len = std::strlen(src);
            wchar_t * tmp = new wchar_t[len + 1];
            std::mbstowcs(tmp,src,len + 1);
            buf = tmp;
            delete [] tmp;
	    
            return buf.c_str();
        }

        // 字符串操作
        static inline size_t strlen(const char * src){
            return std::strlen(src);
        }

        static inline const charType * strchg(const char * src){
            return src;
        }

        static inline const charType * strconst(const char * src){
            return src;
        }
	
        // IO 操作
        static inline intType fputc(std::FILE * fp,intType c){
            return std::putc(c,fp);
        }

        static inline intType fgetc(std::FILE * fp){
            return std::getc(fp);
        }

        static inline bool fputs(std::FILE * fp,const charPtr src){
            return std::fputs(src,fp) != EOF;
        }
	
        static inline bool fgets(std::FILE * fp,charPtr src,int size){
            return std::fgets(src,size,fp) != NULL;
        }

        static inline int ungetc(std::FILE * fp,intType c){
            return std::ungetc(c,fp);
        }

        // 按二进制形式来读字符。。。
        static inline int fread(std::FILE * fp, charPtr src, int size){
            if(size <= 0) return 0;
            return std::fread(src, sizeof(charType), size, fp);
        }
    };

    template<>
    class charLib<wchar_t>{
        charLib() = delete;
    public:
        using charType = wchar_t;
        using charPtr = wchar_t *;
        using intType = wint_t;
        using strType = std::wstring;
	
        static inline intType empty(){
            return L'\0';
        }

        static inline intType enter(){
            return L'\n';
        }

        static inline intType eof(){
            return WEOF;
        }
        
        static inline bool isalnum(charType ch){
            return static_cast<bool>(std::iswalnum(ch));
        }

        static inline bool isalpha(charType ch){
            return static_cast<bool>(std::iswalpha(ch));
        }

        static inline bool islower(charType ch){
            return static_cast<bool>(std::iswlower(ch));
        }

        static inline bool isupper(charType ch){
            return static_cast<bool>(std::iswupper(ch));
        }

        static inline bool isdigit(charType ch){
            return static_cast<bool>(std::iswdigit(ch));
        }

        static inline bool isxdigit(charType ch){
            return static_cast<bool>(std::iswxdigit(ch));
        }

        static inline bool iscntrl(charType ch){
            return static_cast<bool>(std::iswcntrl(ch));
        }

        static inline bool isgraph(charType ch){
            return static_cast<bool>(std::iswgraph(ch));
        }

        static inline bool isspace(charType ch){
            return static_cast<bool>(std::iswspace(ch));
        }

        static inline bool isblank(charType ch){
            return static_cast<bool>(std::iswblank(ch));
        }

        static inline bool isprint(charType ch){
            return static_cast<bool>(std::iswprint(ch));
        }

        static inline bool ispunct(charType ch){
            return static_cast<bool>(std::iswpunct(ch));
        }

        static inline charType tolower(charType ch){
            return static_cast<charType>(std::towlower(ch));
        }

        static inline charType toupper(charType ch){
            return static_cast<charType>(std::towupper(ch));
        }

        // 字符串操作
        static inline size_t strlen(const wchar_t * src){
            return std::wcslen(src);
        }

        static inline const charType * strchg(const char * src){
            return charLib<char>::towstr(src);
        }

        static inline strType strchg(const std::string & src){
            return strType(charLib<char>::towstr(src.c_str()));
        }
	
        static inline const charType * strconst(const char * src){
            return charLib<char>::towstr(src);
        }
	
        // IO 操作
        static inline intType fputc(std::FILE * fp,intType c){
            return std::putwc(c,fp);
        }

        static inline intType fgetc(std::FILE * fp){
            return std::getwc(fp);
        }

        static inline bool fputs(std::FILE * fp,const charPtr src){
            return std::fputws(src,fp) != (int)WEOF;	
        }
	
        static inline bool fgets(std::FILE * fp,charPtr dst,int size){
            return std::fgetws(dst,size,fp) != NULL;
        }

        static inline int ungetc(std::FILE * fp,intType c){
            return std::ungetwc(c,fp);
        }

        // 按二进制形式来读字符。。。
        static inline int fread(std::FILE * fp, charPtr src, int size){
            if(size <= 0) return 0;
            return std::fread(src, sizeof(charType), size, fp);
        }

    };

}

#endif
